﻿using System;
using System.Data;
using System.Collections;
using System.Data.Common;
using System.Collections.Generic;

namespace Titan
{
    /// <summary>
    /// sql解析器，根据对象生成sql语句,将查询结果赋值给对象等
    /// </summary>
    public interface ISqlProvider
    {
        Dictionary<EntityType, ITable> Tables { get; }
        Dictionary<EntityType, IStatement> Statements { get; }
        /// <summary>
        /// 根据实体对象类型返回映射信息，如果没有找到函数内部就会抛出异常
        /// </summary> 
        /// <param name="entityType">实体对象类型，针对非实现IDynamicEntity接口的类使用</param>
        /// <returns>映射信息</returns>
        ITable GetTableByEntityType(EntityType entityType);


        ///// <summary>
        ///// 伪造一个column
        ///// </summary>
        ///// <returns></returns>
        //IColumn CreateCountColumn();


        /// <summary>
        /// 根据实体对象类型返回映射信息，如果没有找到函数内部就会抛出异常
        /// </summary>
        /// <param name="commandType">命令对象类型</param>
        /// <returns>映射信息</returns>
        IStatement GetStatementByType(EntityType commandType);
        

        /// <summary>
        /// 创建一个数据库连接实例，如针对oracle应当返回OracleConnection
        /// </summary>
        /// <returns></returns>
        IDbConnection CreateConnection();


        /// <summary>
        /// 创建一个DataAdapter实例，例如针对oracle应当返回OracleDataAdapter
        /// </summary>
        /// <returns></returns>
        DbDataAdapter CreateDataAdapter();


        /// <summary>
        /// 对传入的command对象的CommandText包装一层分页sql，例如针对oracle数据库拼接的sql中可能包含rownum
        /// </summary>
        /// <param name="session"></param>
        /// <param name="command"></param>
        /// <param name="pageSize">每页记录数，必须是>=0</param>
        /// <param name="pageIndex">从1开始的页码，必须是>=1</param>
        /// <returns></returns>
        void WrapPaging(IDbSession session, IDbCommand command, int pageSize, int pageIndex);


        /// <summary>
        /// 将查询结果集dataReader中的数据填充到实体对象的某个属性
        /// </summary>
        /// <param name="valueFromDataReader">datareader中取回的值</param> 
        /// <param name="expectedType">预期返回的类型</param> 
        object ConvertDbValue(object value, Type expectedType);



        /// <summary>
        /// 根据obj对象的映射信息(ITable)，生成insert语句并执行。注意必须传入实体类，因为需要承载数据库返回值
        /// </summary>
        /// <param name="session"></param>
        /// <param name="tableMapping"></param>
        /// <param name="entityType"></param>
        /// <param name="nameValues">需要生成insert的属性列表</param>
        /// <param name="entity">如果有数据库返回值，则会存储到这个对象中</param>
        /// <returns></returns>
        int Insert(IDbSession session, IDictionary<string, string> tableMapping, EntityType entityType,INameValueExpressionCollection nameValues,object entity);


        /// <summary>
        /// 批量修改
        /// </summary>
        /// <param name="session"></param>
        /// <param name="tableMapping"></param>
        /// <param name="conditionCollection"></param>
        /// <param name="entity"></param>
        /// <param name="updatePropertyNames"></param>
        /// <returns></returns>
        int Update(IDbSession session, IDictionary<string, string> tableMapping, EntityType entityType,IUpdateExpression updateExpression);



        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="session"></param>
        /// <param name="tableMapping"></param>
        /// <param name="entityType"></param>
        /// <param name="conditionCollection"></param>
        /// <returns></returns>
        int Delete(IDbSession session, IDictionary<string, string> tableMapping, EntityType entityType, IConditionCollection conditionCollection);


         

        /// <summary>
        /// 
        /// </summary>
        /// <param name="session"></param>
        /// <param name="tableMapping"></param>
        /// <param name="list"></param>
        /// <param name="clearListBeforeFill">是否在填充前要清除list</param>
        /// <param name="entityType"></param>
        /// <param name="queryExpression"></param>
        /// <returns>如果在queryExpression指定了ReturnMatchedCount为true，则返回全部匹配数，否则返回实际读到的个数</returns>
        int SelectCollection(IDbSession session, IDictionary<string, string> tableMapping, EntityType entityType, IList list, IQueryExpression queryExpression, bool clearListBeforeFill);



        int SelectCount(IDbSession session, IDictionary<string, string> tableMapping, EntityType entityType, IConditionCollection conditionCollection);


        /// <summary>
        /// 考虑性能问题，如果使用selectCount则数据库扫描数据量比较大
        /// </summary>
        /// <param name="session"></param>
        /// <param name="tableMapping"></param>
        /// <param name="entityType"></param>
        /// <param name="conditionCollection"></param>
        /// <returns></returns>
        bool Exists(IDbSession session, IDictionary<string, string> tableMapping, EntityType entityType, IConditionCollection conditionCollection);


        void ExecuteReaderAndFill(IDbSession session, object command, IList[] lists, EntityType[] entityTypes);

        IDataReader ExecuteReader(IDbSession session, object command);

        int ExecuteNonQuery(IDbSession session, object command); 

        
    }
}
